package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemClient;
import com.hmall.common.client.UserClient;
import com.hmall.common.dto.Address;
import com.hmall.common.dto.Item;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.pojo.RequestParams;
import com.hmall.order.service.IOrderService;
import com.hmall.order.utils.UserHolder;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;

@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private UserClient userClient;
    @Autowired
    private IOrderLogisticsService orderLogisticsService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Transactional
    @Override
    //创建订单
    public Long creatOrder(RequestParams params) {
        //订单对象
        Order order = new Order();
        //查询商品
        Item item = itemClient.getById(params.getItemId());
        //基于商品价格、购买数量计算商品总价：totalFee
        long totalFee = item.getPrice()*params.getNum();
        order.setTotalFee(totalFee);
        order.setPaymentType(params.getPaymentType());
        order.setUserId(UserHolder.getUser());
        order.setStatus(Order.OrderStatus.UNPAY.getState());
        //将Order写入数据库tb_order表中
        this.save(order);
        //将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        OrderDetail detail = new OrderDetail();
        detail.setName(item.getName());
        detail.setSpec(item.getSpec());
        detail.setPrice(item.getPrice());
        detail.setNum(params.getNum());
        detail.setItemId(item.getId());
        detail.setImage(item.getImage());
        detail.setOrderId(order.getId());
        orderDetailService.save(detail);

        //根据addressId查询user-service服务，获取地址信息
        Address address = userClient.findAddressById(params.getAddressId());

        //将地址封装为OrderLogistics对象，写入tb_order_logistics表
        OrderLogistics orderLogistics = new OrderLogistics();
        BeanUtils.copyProperties(address,orderLogistics);
        orderLogistics.setOrderId(order.getId());
        orderLogisticsService.save(orderLogistics);

        //扣减库存
        try {
            itemClient.updateStock(item.getId(),params.getNum());
        } catch (Exception e) {
            throw new RuntimeException("库存不足!");
        }

        //清理超时未支付订单(延迟消息,超时30分钟后，订单就会取消)
        //清理超时未支付订单(延迟消息,超时30分钟后，订单就会取消)
        //交换机名称
        String exchangeName ="delay.direct";
        //routingKey
        String routingKey = "delay";
        //消息
        String msg = order.getId().toString();
        //延时
        Long delayTimeMills = 30L*60*1000;
        Message message = MessageBuilder.withBody(msg.getBytes(StandardCharsets.UTF_8)).setHeader("x-delay",delayTimeMills).build();
        //消息id
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,routingKey,message,correlationData); //队列名称,消息

        return order.getId();
    }


    @Override
    public void cancelOrder(Long orderId) {
        //根据orderId查询订单
        Order order = getById(orderId);
        //判断订单status是否为1 (不为1则丢弃, 为1则继续)
        if( order.getStatus() != Order.OrderStatus.UNPAY.getState() ){
            return;
        }
        //根据orderId修改订单status为5（取消），注意幂等判断，避免重复消息
        order.setStatus(Order.OrderStatus.CANCEL.getState());
        updateById(order);

        //恢复库存
        List<OrderDetail> orderDetailList = orderDetailService.query().eq("order_id", orderId).list();
        for (OrderDetail detail : orderDetailList) {
            //根据orderId查询订单详情，得到商品购买数量
            Integer num = detail.getNum();
            //调用item-service，根据商品id、商品数量恢复库存
            itemClient.updateStock(detail.getItemId(), num*-1);
        }
    }
}
